﻿using System;
using System.Security.Principal;
using System.Linq;
using Tiscs.Practices.Diagnostics;

namespace Tiscs.Practices.Security
{
    /// <summary>
    /// 权限描述基类。
    /// </summary>
    public abstract class AuthorityBase
    {
        /// <summary>
        /// 验证一个用户是否符合该权限描述
        /// </summary>
        /// <param name="user">要验证权限的用户。</param>
        /// <returns>布尔值。用户是否符合权限描述的。</returns>
        public virtual bool Verify(IPrincipal user)
        {
            Exception exception;
            if (!Validation.Parameter<IPrincipal>(nameof(user)).AssertNotNull().CheckRules(user, out exception))
            {
                throw exception;
            }
            string[] allowUserArray = GetAllowUserArray();
            string[] allowRoleArray = GetAllowRoleArray();
            string[] denyUserArray = GetDenyRoleArray();
            string[] denyRoleArray = GetDenyRoleArray();
            if (!user.Identity.IsAuthenticated)
            {
                return false;
            }
            if (!IsNullOrEmptyArray(denyUserArray) && denyUserArray.Contains(user.Identity.Name, StringComparer.CurrentCultureIgnoreCase))
            {
                return false;
            }
            if (!IsNullOrEmptyArray(denyRoleArray) && user.IsInRoles(denyRoleArray))
            {
                return false;
            }
            if (IsNullOrEmptyArray(allowUserArray) && IsNullOrEmptyArray(allowRoleArray))
            {
                return true;
            }
            if (!IsNullOrEmptyArray(allowUserArray))
            {
                return allowUserArray.Contains(user.Identity.Name, StringComparer.CurrentCultureIgnoreCase);
            }
            if (!IsNullOrEmptyArray(allowRoleArray))
            {
                return user.IsInRoles(allowRoleArray);
            }
            return false;
        }

        /// <summary>
        /// 判断集合对象是否为null或为空。
        /// </summary>
        /// <param name="array">要验证的集合。</param>
        /// <returns>布尔值。集合对象是否为null或为空。</returns>
        private bool IsNullOrEmptyArray(string[] array)
        {
            return array == null || array.Length == 0;
        }

        /// <summary>
        /// 获取授权访问的用户列表。
        /// </summary>
        /// <returns>授权访问的用户列表。</returns>
        protected abstract string[] GetAllowUserArray();

        /// <summary>
        /// 获取授权访问的角色列表。
        /// </summary>
        /// <returns>授权访问的角色列表。</returns>
        protected abstract string[] GetAllowRoleArray();

        /// <summary>
        /// 获取拒绝访问的用户列表。
        /// </summary>
        /// <returns>拒绝访问的用户列表。</returns>
        protected abstract string[] GetDenyUserArray();

        /// <summary>
        /// 获取拒绝访问的角色列表。
        /// </summary>
        /// <returns>拒绝访问的角色列表。</returns>
        protected abstract string[] GetDenyRoleArray();
    }

}
